<template>
	<div
		ref="dragVerify"
		class="drag_verify"
		:style="dragVerifyStyle"
		@mousemove="dragMoving"
		@mouseup="dragFinish"
		@mouseleave="dragFinish"
		@touchmove="dragMoving"
		@touchend="dragFinish"
	>
		<div class="dv_progress_bar" :class="{ goFirst2: isOk }" ref="progressBar" :style="progressBarStyle"></div>
		<div class="dv_text" :style="textStyle" ref="message">
			<slot name="textBefore" v-if="$slots.textBefore"></slot>
			{{ message }}
			<slot name="textAfter" v-if="$slots.textAfter"></slot>
		</div>

		<div
			class="dv_handler dv_handler_bg"
			:class="{ goFirst: isOk }"
			@mousedown="dragStart"
			@touchstart="dragStart"
			ref="handler"
			:style="handlerStyle"
		>
			<i :class="handlerIcon"></i>
		</div>
	</div>
</template>
<script lang="ts">
import { ref, onMounted, getCurrentInstance, computed, defineProps, defineComponent, defineEmits, nextTick } from 'vue'
export default defineComponent({
	name: 'dragVerifyMain',
})
</script>
<script setup lang="ts">
const define = defineProps({
	isPassing: {
		type: Boolean,
		default: false,
	},
	width: {
		type: Number,
		default: 250,
	},
	height: {
		type: Number,
		default: 40,
	},
	text: {
		type: String,
		default: 'swiping to the right side',
	},
	successText: {
		type: String,
		default: 'success',
	},
	background: {
		type: String,
		default: '#eee',
	},
	progressBarBg: {
		type: String,
		default: '#76c61d',
	},
	completedBg: {
		type: String,
		default: '#76c61d',
	},
	circle: {
		type: Boolean,
		default: false,
	},
	radius: {
		type: String,
		default: '4px',
	},
	handlerIcon: {
		type: String,
	},
	successIcon: {
		type: String,
	},
	handlerBg: {
		type: String,
		default: '#fff',
	},
	textSize: {
		type: String,
		default: '14px',
	},
	textColor: {
		type: String,
		default: '#333',
	},
})
let isMoving = ref<boolean>(false)
let isOk = ref<boolean>(false)
let x = ref<number>(0)
const props = getCurrentInstance() as any
const emit = defineEmits(['handlerMove', 'passfail', 'update:isPassing', 'passcallback'])
const handlerStyle = computed(() => {
	return {
		width: define.height + 'px',
		height: define.height + 'px',
		background: define.handlerBg,
	}
})
const message = computed(() => {
	return define.isPassing ? define.successText : define.text
})
const dragVerifyStyle = computed(() => {
	return {
		width: define.width + 'px',
		height: define.height + 'px',
		lineHeight: define.height + 'px',
		background: define.background,
		borderRadius: define.circle ? define.height / 2 + 'px' : define.radius,
	}
})
const progressBarStyle = computed(() => {
	return {
		background: define.progressBarBg,
		height: define.height + 'px',
		borderRadius: define.circle ? define.height / 2 + 'px 0 0 ' + define.height / 2 + 'px' : define.radius,
	}
})
const textStyle = computed(() => {
	return {
		height: define.height + 'px',
		width: define.width + 'px',
		fontSize: define.textSize,
	}
})
onMounted(() => {
	nextTick(() => {
		const dragEl = props.refs.dragVerify
			dragEl.style.setProperty('--textColor', define.textColor)
			dragEl.style.setProperty('--width', Math.floor(define.width / 2) + 'px')
			dragEl.style.setProperty('--pwidth', -Math.floor(define.width / 2) + 'px')
	})
})
const dragStart = function (e: MouseEvent) {
	if (!define.isPassing) {
		isMoving.value = true
		x.value = e.pageX || e.touches[0].pageX
	}
	emit('handlerMove')
}
interface MouseEvent {
	touches?: any
	pageX?: any
	changedTouches?: any
}
const dragMoving = function (e: MouseEvent) {
	if (isMoving.value && !define.isPassing) {
		var _x = (e.pageX || e.touches[0].pageX) - x.value
		var handler = props.refs.handler
		if (_x > 0 && _x <= define.width - define.height) {
			handler.style.left = _x + 'px'
			props.refs.progressBar.style.width = _x + define.height / 2 + 'px'
		} else if (_x > define.width - define.height) {
			handler.style.left = define.width - define.height + 'px'
			props.refs.progressBar.style.width = define.width - define.height / 2 + 'px'
			passVerify()
		}
	}
}
const dragFinish = function (e: MouseEvent) {
	if (isMoving.value && !define.isPassing) {
		var _x = (e.pageX || e.changedTouches[0].pageX) - x.value
		if (_x < define.width - define.height) {
			isOk.value = true
			setTimeout(function () {
				props.refs.handler.style.left = '0'
				props.refs.progressBar.style.width = '0'
				isOk.value = false
			}, 500)
			emit('passfail')
		} else {
			var handler = props.refs.handler
			handler.style.left = define.width - define.height + 'px'
			props.refs.progressBar.style.width = define.width - define.height / 2 + 'px'
			passVerify()
		}
		isMoving.value = false
	}
}
const passVerify = function () {
	emit('update:isPassing', true)
	isMoving.value = false
	var handler = props.refs.handler
	handler.children[0].className = define.successIcon
	props.refs.progressBar.style.background = define.completedBg
	props.refs.message.style['-webkit-text-fill-color'] = 'unset'
	props.refs.message.style.animation = 'slidetounlock2 3s infinite'
	props.refs.message.style.color = '#fff'
	emit('passcallback')
}
</script>
<style scoped>
.drag_verify {
	position: relative;
	background-color: #e8e8e8;
	text-align: center;
	overflow: hidden;
}
.drag_verify .dv_handler {
	position: absolute;
	top: 0px;
	left: 0px;
	cursor: move;
}
.drag_verify .dv_handler i {
	color: #666;
	padding-left: 0;
	font-size: 16px;
}
.drag_verify .dv_handler .el-icon-circle-check {
	color: #6c6;
	margin-top: 9px;
}
.drag_verify .dv_progress_bar {
	position: absolute;
	height: 34px;
	width: 0px;
}
.drag_verify .dv_text {
	position: absolute;
	top: 0px;
	color: transparent;
	-moz-user-select: none;
	-webkit-user-select: none;
	user-select: none;
	-o-user-select: none;
	-ms-user-select: none;
	background: -webkit-gradient(
		linear,
		left top,
		right top,
		color-stop(0, var(--textColor)),
		color-stop(0.4, var(--textColor)),
		color-stop(0.5, #fff),
		color-stop(0.6, var(--textColor)),
		color-stop(1, var(--textColor))
	);
	-webkit-background-clip: text;
	-webkit-text-fill-color: transparent;
	-webkit-text-size-adjust: none;
	animation: slidetounlock 3s infinite;
}
.drag_verify .dv_text * {
	-webkit-text-fill-color: var(--textColor);
}
.goFirst {
	left: 0px !important;
	transition: left 0.5s;
}
.goFirst2 {
	width: 0px !important;
	transition: width 0.5s;
}
</style>
<style>
@-webkit-keyframes slidetounlock {
	0% {
		background-position: var(--pwidth) 0;
	}
	100% {
		background-position: var(--width) 0;
	}
}
@-webkit-keyframes slidetounlock2 {
	0% {
		background-position: var(--pwidth) 0;
	}
	100% {
		background-position: var(--pwidth) 0;
	}
}
</style>
